package rad.framework.conv;

import java.util.ArrayList;
import java.util.List;

import rad.framework.lang.ReflectionUtil;
import rad.framework.xml.XmlUtil;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public abstract class DomImportCommand<E> extends ImportCommand<E> {

	public DomImportCommand(String persistenceUnitJndiName) {
		super(persistenceUnitJndiName);
	}

	@Override
	protected Object transform() {
		Document document = XmlUtil.parse(getXml());
		List<Element> nodes = getNodes(document);
		return transform(nodes);
	}

	protected abstract Object transform(List<Element> nodes);

	protected List<Element> getNodes(Document document) {
		List<Element> list = new ArrayList<Element>();
		Element root = document.getDocumentElement();
		if ("ArrayList".equals(root.getNodeName())) {
			Node node = root.getFirstChild();
			while (node != null) {
				if (node.getNodeType() != Node.TEXT_NODE) {
					list.add((Element) node);
				}
				node = node.getNextSibling();
			}
		} else {
			list.add(root);
		}
		return list;
	}

	protected void map(Element src, Object tgt, String name) {
		map(src, name, tgt, name);
	}

	protected void map(Element src, String srcName, Object tgt, String tgtName) {
		List<Element> nodes = getElementsByTagName(src, srcName);
		int length = nodes.size();
		if (length == 1) {
			Element node = (Element) nodes.get(0);
			String value = node.getTextContent();
			ReflectionUtil.setProperty(tgt, tgtName, value);
		} else if (length > 1) {
			StringBuilder builder = new StringBuilder();
			for (Element element : nodes) {
				String value = element.getTextContent();
				builder.append(value);
				builder.append("|");
			}
			throw new RuntimeException(srcName
					+ ": appears to be a collection. use a getter first. - "
					+ builder.toString());
		} else {
			// do nothing for zero
		}
	}

	protected List<Element> getElementsByTagName(Element src, String srcName) {
		List<Element> list = new ArrayList<Element>();
		NodeList nodes = src.getElementsByTagName(srcName);
		int length = nodes.getLength();
		for (int i = 0; i < length; i++) {
			Element node = (Element) nodes.item(i);
			if (node.getParentNode().equals(src)) {
				list.add(node);
			}
		}
		return list;
	}
}
